package dyyx.util;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.status.Status;
import com.alibaba.dubbo.common.store.DataStore;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.support.AbstractRegistryFactory;
import com.alibaba.dubbo.remoting.exchange.ExchangeServer;
import com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol;

public abstract class DubboStatusUtil {

	public static Map<String, Object> getStatus() {
		Map<String, Object> map = new LinkedHashMap<>();

		Collection<Registry> regsitries = AbstractRegistryFactory.getRegistries();
		map.put("regsitries", getRegistryInfo(regsitries));

		Collection<ExchangeServer> servers = DubboProtocol.getDubboProtocol().getServers();
		if (servers != null) {
			map.put("serversSize", servers.size());
			for (ExchangeServer server : servers) {
				String info = server.getLocalAddress() + "," + server.getChannels().size() + "," + server.getUrl();
				map.put(server.getLocalAddress().toString(), info);
			}

		}

		map.put("threadPoolInfo", getThreadPoolInfo());

		return map;
	}

	private static Map<String, Object> getRegistryInfo(Registry reg) {
		if (reg == null) {
			return null;
		}
		Map<String, Object> map = new LinkedHashMap<>();
		map.put("available", reg.isAvailable());
		map.put("url", reg.getUrl().toString());
		return map;
	}

	private static Map<String, Object> getRegistryInfo(Collection<Registry> regsitries) {
		if (regsitries == null || regsitries.isEmpty()) {
			return null;
		}
		Map<String, Object> map = new LinkedHashMap<>();
		map.put("size", regsitries.size());

		int index = 0;
		for (Registry item : regsitries) {
			index++;
			map.put("registry" + index, getRegistryInfo(item));
		}
		return map;
	}

	private static String getThreadPoolInfo() {
		DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
		Map<String, Object> executors = dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);

		StringBuilder msg = new StringBuilder();
		Status.Level level = Status.Level.OK;
		for (Map.Entry<String, Object> entry : executors.entrySet()) {
			String port = entry.getKey();
			ExecutorService executor = (ExecutorService) entry.getValue();

			if (executor != null && executor instanceof ThreadPoolExecutor) {
				ThreadPoolExecutor tp = (ThreadPoolExecutor) executor;
				boolean ok = tp.getActiveCount() < tp.getMaximumPoolSize() - 1;
				Status.Level lvl = Status.Level.OK;
				if (!ok) {
					level = Status.Level.WARN;
					lvl = Status.Level.WARN;
				}

				if (msg.length() > 0) {
					msg.append(";");
				}
				msg.append("Pool status:" + lvl + ", max:" + tp.getMaximumPoolSize() + ", core:" + tp.getCorePoolSize()
						+ ", largest:" + tp.getLargestPoolSize() + ", active:" + tp.getActiveCount() + ", task:"
						+ tp.getTaskCount() + ", service port: " + port);
			}
		}
		return msg.toString();
	}

}
